package board.grid;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/** A base class for Grids to cover most of
 *  the general logic.  The functionality of
 *  this class will suffice for most Grid implementations.  
 *  
 * @see Grid
 * 
 * @author R.Wisniewski1101
 *
 * @param <T> - the type of occupants in this Grid
 */
public abstract class AbstractGrid<T> implements Grid<T>{
	/** The contents of the Grid.  Most of the
	 *  work with the occupant involves manipulating
	 *  this the contents of this map.  
	 */
	protected Map<Space, T> occupents;
	/** Constructs a new, empty grid.  */
	public AbstractGrid() {
		occupents = new HashMap<Space, T>();
	}
	@Override
	public Collection<T> getAll() {return occupents.values();}
	@Override
	public Space getCurrentSpace(Object occupant) {
		Collection<Space> spaces = getOccupiedSpaces();
		for(Space s : spaces)
			if(get(s) == occupant)
				return s;
		return null;
	}
	@Override
	public Collection<Space> getOccupiedSpaces() {return occupents.keySet();}
	@Override
	public T put(Space space, T newOccupent) {
		if(!isValidSpace(space) || newOccupent == null)
			throw new IllegalArgumentException("The selected space is not valid on this grid. ");
		if(occupents.containsValue(newOccupent))
			occupents.remove(getCurrentSpace(newOccupent));
		T orig = get(space);
		occupents.put(space, newOccupent);
		return orig;
	}
	@Override
	public T remove(Space space) {return occupents.remove(space);}
	@Override
	public T get(Space space) {return occupents.get(space);}
	@Override
	public Collection<Space> getValidSurroundingSpaces(Space space)
			{return getValidSurroundingSpaces(space, 1);}
	@Override
	public Collection<Space> getValidSurroundingSpaces(Space space, int radius) {
		Collection<Space> spaces = space.getSurroundingSpaces(radius);
		ArrayList<Space> validSpaces = new ArrayList<Space>();
		for(Space s : spaces)
			if(isValidSpace(s))
				validSpaces.add(s);
		return validSpaces;
	}
	@Override
	public Collection<Space> getEmptySurroundingSpaces(Space space)
			{return getEmptySurroundingSpaces(space, 1);}
	@Override
	public Collection<Space> getEmptySurroundingSpaces(Space space, int radius) {
		Collection<Space> surroundingSpaces = getValidSurroundingSpaces(space, radius);
		surroundingSpaces.removeAll(occupents.keySet());
		return surroundingSpaces;
	}
	@Override
	public Collection<Space> getOccupiedSurroundingSpaces(Space space)
			{return getOccupiedSurroundingSpaces(space, 1);}
	@Override
	public Collection<Space> getOccupiedSurroundingSpaces(Space space, int radius) {
		Collection<Space> surroundingSpaces = getValidSurroundingSpaces(space, radius);
		surroundingSpaces.retainAll(occupents.keySet());
		return surroundingSpaces;
	}
	@Override
	public Collection<T> getSurroundingOccupents(Space space)
			{return getSurroundingOccupents(space, 1);}
	@Override
	public Collection<T> getSurroundingOccupents(Space space, int radius) {
		Collection<Space> spaces = getOccupiedSurroundingSpaces(space, radius);
		ArrayList<T> occupentList = new ArrayList<T>();
		for(Space s : spaces)
			occupentList.add(get(s));
		return occupentList;
	}
	
	@Override
	public Iterable<T> allOccupants() {return getAll();}
	@Override
	public Iterable<Space> allOccupiedSpaces() {return occupents.keySet();}
}